package network;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

//回显服务器
public class UdpEchoServer {

    //调用这个类时,创建出一个socket对象用来操作网卡,与外界进行通信
    private DatagramSocket socket = null;

    //因为是服务器所以要指定一个明确的端口号,别人才能知道往这个端口发请求
    public UdpEchoServer(int port) throws SocketException {
        socket = new DatagramSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器(原神)启动!!!");
        //while循环是为了只要有请求服务器就接收
        //但是当没有请求进入的时候可能会被receive阻塞
        //同样的如果请求过多,while循环处理不过来可能会导致服务器跪了
        while (true) {
            //首先要用一个DatagramPacket对象来接受,这个对象一开始时空的,
            // 然后放入到DatagramSocket中调用receive方法来填充这个对象
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);
            socket.receive(requestPacket);
            //为了方便处理,这里我们将requestPacket填充后的对象转化为String字符串进行处理
            //下面这三个参数分别表示:1.取出填充后的字节数组 2.开始的位置 3.字节数组实际的长度(因为可能不会用满)
            String request = new String(requestPacket.getData(),0,requestPacket.getLength());
            //根据请求来计算响应(这里我们就自己写一个简单的返回字符串本身,不做复杂的处理)
            String response = process(request);
            //此时我们就要将响应的结果发送出去,所以也要构造出一个DatagramPacket对象
            //但是此时的DatagramPacket对象不能再是空的对象了,要用我们已经计算好结果的响应来发送
            //所以此时我们要对DatagramPacket对象的参数进行一个设定
            //1.获取到响应结果(字符串)的字节数组,2.获取到字节的长度(所以要先传化为字节数组再获取长度)
            //3.要指定发放的地址(这里的地址要包含ip地址和端口号)
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length
            ,requestPacket.getSocketAddress());
            socket.send(responsePacket);
            //最后打印一下中间处理的结果
            //格式为:ip地址,端口号,请求,响应
            System.out.printf("[%s:%d] req : %s; res : %s\n",requestPacket.getAddress().toString() ,
                    requestPacket.getPort(),request,response);
        }
    }
    public String process(String s) {
        return s+" 曹宸煊o(￣▽￣)ｄ";
    }

    public static void main(String[] args) throws IOException {
        UdpEchoServer server = new UdpEchoServer(9090);
        server.start();
    }

}
